const db = require('@/db/db-connection')
const { dateFormat } = require('@/utils/common.util')

class ImModel {
  constructor () {
    this.tableName = 'im'
  }

  async create (params) {
    const { id, fromId, toId, content, image, sys, imageWidth, imageHeight, sendTime, sendTimeStamp, receiveTime, quoteContent } = params
    const { quoteId, quoteText, quoteImage, quoteNickname } = quoteContent || {}
    console.log(quoteContent)
    const createTime = dateFormat(new Date())
    try {
      const sql = `INSERT INTO ${this.tableName} (id, fromId, toId, content, image, sys, imageWidth, imageHeight, sendTime, sendTimeStamp, receiveTime, createTime, quoteId, quoteText, quoteImage, quoteNickname)
      
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`

      await db.query(sql, [id, fromId, toId, content, image, sys, imageWidth, imageHeight, sendTime, sendTimeStamp, receiveTime, createTime, quoteId, quoteText, quoteImage, quoteNickname])

      return id
    } catch (error) {
      throw new Error(error)
    }
  }

  /**
   * 根据发送人和接收人id获取双方的分页聊天记录
   * @param {*} fromId
   * @param {*} toId
   */
  async findPage (fromerId, toerId, pageNo, pageSize) {
    const sql = `SELECT * FROM ${this.tableName} WHERE 
      
      ((fromId = '${fromerId}' AND toId = '${toerId}') OR (fromId = '${toerId}' AND toId = '${fromerId}')) AND (ISNULL(deleteIds) OR deleteIds != '${fromerId}')
      
      ORDER BY sendTimeStamp DESC, id ASC LIMIT ${(pageNo - 1) * pageSize}, ${pageSize}`

    const totalSql = `SELECT COUNT(*) as total FROM ${this.tableName} WHERE 
      
      ((fromId = '${fromerId}' AND toId = '${toerId}') OR (fromId = '${toerId}' AND toId = '${fromerId}')) AND (ISNULL(deleteIds) OR deleteIds != '${fromerId}')`

    try {
      const [list, total] = [await db.query(sql), await db.query(totalSql)]

      return {
        list: list.reverse(),

        total: total[0].total,

        pageNo: Number(pageNo)
      }
    } catch (error) {
      throw new Error(error)
    }
  }

  /**
   * 根据用户id查询当前用户聊天的成员列表
   * @param {*} userId
   * @returns
   */
  async findChatPersonList (userId) {
    const sql = `select tt.userId, user.avatar, user.description, user.nickname, im.sendTime, im.content as lastChatRecord, im.image as lastChatImage, t.sendTimeStamp as sort,
      (select count(*) from im where im.fromId = tt.userId and im.toId = '${userId}' and im.receiverRead = '0' and isnull(sys)) as count from 
      (select userId, MAX(sendTimeStamp) AS sendTimeStamp from 
        (
          (select distinct t.toId as userId, sendTimeStamp FROM im t WHERE fromId = '${userId}' and (deleteIds != '${userId}' or isnull(deleteIds))) 
          union 
          (select distinct t.fromId as userId, sendTimeStamp FROM im t WHERE toId = '${userId}' and (deleteIds != '${userId}' or isnull(deleteIds)))
          union 
          (select distinct t.toId as userId, null as sendTimeStamp FROM top_im t WHERE fromId = '${userId}')
        ) as tt group by tt.userId
      ) as tt
      left join user on user.id = tt.userId
      left join im on 
      (tt.sendTimeStamp = im.sendTimeStamp) and 
      ((tt.userId = im.fromId and im.toId = '${userId}') || (tt.userId = im.toId and im.fromId = '${userId}')) 
      left join top_im t on t.toId = tt.userId and t.fromId = '${userId}' 
      order by sort desc, tt.sendTimeStamp desc`

    try {
      const data = await db.query(sql, [userId, userId])

      return data
    } catch (error) {
      throw new Error(error)
    }
  }

  /**
   * 单条聊天记录删除
   * @param {*} imId
   * @param {*} userId
   */
  async deleteSingleIm (imId, userId) {
    const sql1 = `DELETE FROM im WHERE id = '${imId}' AND deleteIds IS NOT NULL AND deleteIds != '${userId}'`

    const sql2 = `UPDATE im SET deleteIds = '${userId}' WHERE id = '${imId}' AND ISNULL(deleteIds)`

    try {
      await db.query(sql1)
      await db.query(sql2)
    } catch (error) {
      throw new Error(error)
    }
  }

  /**
   * 根据聊天记录id删除聊天记录
   * @param {*} imId
   */
  async delete (imId) {
    const sql = `DELETE FROM im WHERE id = '${imId}'`

    try {
      await db.query(sql)
    } catch (error) {
      throw new Error(error)
    }
  }

  /**
   * 删除与指定人的所有聊天信息
   * @param {*} fromerId
   * @param {*} toerId
   */
  async deleteChatPersonIm (fromerId, toerId) {
    const sql1 = `DELETE FROM im WHERE 
      ((fromId = '${fromerId}' AND toId = '${toerId}') OR (fromId = '${toerId}' AND toId = '${fromerId}')) 

      AND deleteIds IS NOT NULL AND deleteIds != '${fromerId}'`

    const sql2 = `UPDATE im SET deleteIds = '${fromerId}' WHERE 
    
      ((fromId = '${fromerId}' AND toId = '${toerId}') OR (fromId = '${toerId}' AND toId = '${fromerId}')) 
      
      AND ISNULL(deleteIds)`

    const sql3 = `DELETE FROM top_im WHERE fromId = '${fromerId}' AND toId = '${toerId}'`

    try {
      await db.query(sql1)
      await db.query(sql2)
      await db.query(sql3)
    } catch (error) {
      throw new Error(error)
    }
  }

  /**
   * 查询指定用户所有未读消息总数
   * @param {*} userId
   */
  async getNoReadMessageTotal (userId) {
    const sql = `SELECT COUNT(*) AS total FROM ${this.tableName} WHERE toId = '${userId}' AND receiverRead = '0' AND ISNULL(sys)`
    try {
      const data = await db.query(sql)

      return data[0].total
    } catch (error) {
      throw new Error(error)
    }
  }

  async findOneById (id) {
    const sql = `SELECT * FROM ${this.tableName} WHERE id = ?`

    try {
      const data = await db.query(sql, [id])

      return data[0]
    } catch (error) {
      return null
    }
  }

  /**
   * 批量已读与指定成员在该消息时间之前的所有未读消息
   * @param {*} userId
   * @param {*} toId
   * @param {*} sendTimeStamp
   */
  async batchReadMessage (userId, fromId, sendTimeStamp) {
    const sql = `UPDATE ${this.tableName} SET receiverRead = '1' 
      WHERE fromId = '${fromId}' 
      AND toId = '${userId}' 
      AND sendTimeStamp <= ${sendTimeStamp} 
      AND receiverRead = '0'`
    try {
      await db.query(sql)
    } catch (error) {
      throw new Error(error)
    }
  }

  /**
   * 置顶聊天
   * @param {*} fromId
   * @param {*} toId
   */
  async topIm (fromId, toId) {
    const sendTimeStamp = new Date().getTime()

    const sql = 'INSERT INTO top_im (fromId, toId, sendTimeStamp) VALUES (?, ?, ?)'

    try {
      await db.query(sql, [fromId, toId, sendTimeStamp])
    } catch (error) {
      throw new Error(error)
    }
  }

  async resetTopIm (fromId, toId) {
    const sql = 'DELETE FROM top_im WHERE fromId = ? AND toId = ?'

    try {
      await db.query(sql, [fromId, toId])
    } catch (error) {
      throw new Error(error)
    }
  }
}

module.exports = new ImModel()
